package com.yxl.yxlbus;

import java.util.HashMap;

/**
 * 万能接口：接口管理库
 * 作用：减少重复冗余代码、解耦类之间交互的耦合(例如：fragment与Activity交互、线程与Activity交互)
 * 特点：使用简单、可链式调用。
 */
public class YxlBusManager {
    private static YxlBusManager yxlBusManager;

    public static YxlBusManager getInstance() {
        if (yxlBusManager == null) {
            synchronized (YxlBusManager.class) {
                if (yxlBusManager == null) {
                    yxlBusManager = new YxlBusManager();
                }
            }
        }
        return yxlBusManager;
    }

    private final HashMap<String, YxlBus> hashMap = new HashMap<>();

    /**
     * 将接口添加到容器中，然后可以通过invokeInterface查找对应接口，并触发其里面的函数
     *
     * @param interfaceKey  接口的唯一标识
     * @param yxlBus 接口
     * @return 返回OmnipotentManager实例（作用：方便链式调用）
     */
    public YxlBusManager addInterface(String interfaceKey, YxlBus yxlBus) {
        hashMap.put(interfaceKey, yxlBus);
        return yxlBusManager;
    }

    /**
     * 根据唯一标识去除对应的接口
     *
     * @param interfaceKey 关键字
     */
    public void removeInterface(String interfaceKey) {
        if(hashMap.containsKey(interfaceKey)){
            hashMap.remove(interfaceKey);
        }
    }

    /**
     * 根据唯一标识去除对应的接口
     */
    public HashMap<String, YxlBus> getInterfaceMap() {
        return hashMap;
    }

    /**
     * 通过唯一标识获取对应的无参无返回的接口，并触发其里面的函数，实现回调的功能
     *
     * @param interfaceKey 接口的唯一标识
     */
    public void invokeInterface(String interfaceKey) {
        invokeInterface(interfaceKey, null);
    }

    /**
     * 通过唯一标识获取对应的无参有返回的接口，并触发其里面的函数，实现回调的功能
     *
     * @param interfaceKey 接口的唯一标识
     */
    public <Result> Result invokeInterface(String interfaceKey, Class<Result> resultClass) {
        return invokeInterface(interfaceKey, null, resultClass);
    }

    /**
     * 通过唯一标识获取对应的有参无返回的接口，并触发其里面的函数，实现回调的功能
     *
     * @param interfaceKey 接口的唯一标识
     */
    public <T> void invokeInterface(String interfaceKey, T t) {
        invokeInterface(interfaceKey, t, null);
    }

    /**
     * 通过唯一标识获取对应的有参有返回的接口，并触发其里面的函数，实现回调的功能
     *
     * @param interfaceKey 接口的唯一标识
     */
    public <T, Result> Result invokeInterface(String interfaceKey, T t, Class<Result> resultClass) {
        YxlBus yxlBus = hashMap.get(interfaceKey);
        if (yxlBus == null) {
            throw new NullPointerException("yxlInterface is null for interfaceKey.");
        } else {
            //判断接口对象属于那种类型
            if (yxlBus instanceof YxlBusNoParamNoResult) {
                ((YxlBusNoParamNoResult) yxlBus).function();
            } else if (yxlBus instanceof YxlBusNoParamHasResult) {
                if (resultClass != null) {
                    //转换类型
                    return resultClass.cast(((YxlBusNoParamHasResult) yxlBus).function());
                } else {
                    return (Result) ((YxlBusNoParamHasResult) yxlBus).function();
                }
            } else if (yxlBus instanceof YxlBusHasParamNoResult) {
                ((YxlBusHasParamNoResult) yxlBus).function(t);
            } else if (yxlBus instanceof YxlBusHasParamHasResult) {
                if (resultClass != null) {
                    return resultClass.cast(((YxlBusHasParamHasResult) yxlBus).function(t));
                } else {
                    return (Result) ((YxlBusHasParamHasResult) yxlBus).function(t);
                }
            }
        }
        return null;
    }
}
